package com.mxq.server;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;

import java.util.logging.Logger;

/**
 * @author xiaoqiang
 * @Description 通过 ChannelHandler 来实现服务器的逻辑
 *
 * 关键点要牢记：
 *
 * ChannelHandler 是给不同类型的事件调用
 * 应用程序实现或扩展 ChannelHandler 挂接到事件生命周期和 提供自定义应用逻辑。
 * @date 2019/8/27 18:24
 */
// 1. @Sharable 标识这类的实列之间可以在channel里面共享
@ChannelHandler.Sharable
public class EchoServerHandler extends SimpleChannelInboundHandler<Object> {

    private static final Logger LOGGER = Logger.getLogger("echoServerHandler");

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf in = (ByteBuf) msg;
        // 2.日志消息输出到控制台
        LOGGER.info("Server received: {}"+in.toString(CharsetUtil.UTF_8));
        // 3. 将接收的消息返回给发送者。注意：这里还没有冲刷数据 ctx.flush()
        ctx.write(in);
    }

    /**
     * 处理接收到数据
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // 4. 冲刷所有待审消息到远程节点。关闭通道后，操作完成
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
                .addListener(ChannelFutureListener.CLOSE);
    }

    /**
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause) {
        // 5. 打印异常堆栈跟踪
        cause.printStackTrace();
        // 6. 关闭通道
        ctx.close();
    }
}
